package br.com.felinelayer.server;

import br.com.felinelayer.server.application.Application;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 */
public class Server implements Runnable, IApplicationFactory {

    private static ServerSocket socketServer;
    private int port = 7000;

    private Server() {
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        runServer();
    }

    public static Server runServer() {
        Server server = new Server();
        try {
            new Thread(server).start();
        } catch (Exception ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
        return server;
    }

    @Override
    public void run() {
        if (socketServer == null) {
            try {
                socketServer = new ServerSocket(port);
            } catch (IOException ex) {
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                return;
            }
        }
        // 
        System.out.println("SERVER: waiting clients connection at port " + port);
        try {
            // Loop to wait new connections
            while (true) {
                // Wait new connections
                Socket socket = socketServer.accept();
                // When client conects then runs statement
                System.out.println("SERVER: client connected!");
                // Create client
                ClientServer client = new ClientServer(socket);
                // Execute application thread
                new ApplicationLauncher(this, client).start();
            }
        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Application factory
     *
     * @param applicationName
     * @return Application
     */
    @Override
    public synchronized Application createApplicationByName(String applicationName) {
        try {
            Object o = getClass().getClassLoader().loadClass(applicationName).newInstance();
            if (o instanceof Application) {
                return (Application) o;
            }
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
//        if ( applicationName.equalsIgnoreCase( "sample" ) )
//            return new Sample();
        return null;
    }
}
